package com.yoofn.framework.adapter


import android.databinding.ViewDataBinding
import android.support.v7.util.DiffUtil
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.yanzhenjie.nohttp.NoHttp
import com.yanzhenjie.nohttp.rest.OnResponseListener
import com.yanzhenjie.nohttp.rest.Response
import com.yoofn.framework.R
import com.yoofn.framework.activity.BaseActivity
import com.yoofn.framework.config.LoadMoreConfig
import com.yoofn.framework.fragment.BaseFragment
import com.yoofn.framework.item.BaseItem
import com.yoofn.framework.widget.StatusRecyclerLayout


/**
 * Created by kalshen on 17/4/24.
 * @描述 全局 recyclerLayout 的万能 adapter
 * 适用于 dataBinding 架构 (普通recyclerVIew 无法使用)
 */
class MultiTypeAdapter : RecyclerView.Adapter<MultiTypeAdapter.ItemViewHolder> {

    var loadMoreConfig: LoadMoreConfig? = null

    lateinit var recyclerLayout: StatusRecyclerLayout
    var fragment: BaseFragment<out ViewDataBinding>? = null
    var activity: BaseActivity<out ViewDataBinding>? = null

    constructor(fragment: BaseFragment<out ViewDataBinding>? = null, recyclerLayout: StatusRecyclerLayout, loadMoreConfig: LoadMoreConfig? = null) : super() {
        this.fragment = fragment
        this.recyclerLayout = recyclerLayout
        this.loadMoreConfig = loadMoreConfig
    }

    constructor(activity: BaseActivity<out ViewDataBinding>? = null, recyclerLayout: StatusRecyclerLayout, loadMoreConfig: LoadMoreConfig? = null) : super() {
        this.activity = activity
        this.recyclerLayout = recyclerLayout
        this.loadMoreConfig = loadMoreConfig
    }

    /**
     * adapter 的item 集合
     */
    private var items = ArrayList<BaseItem<out ViewDataBinding>>()

    /**
     * 状态机集合
     * 用于处理所有item 在某一个状态下的不同业务逻辑
     */
    val stateChart = ArrayList<Enum<*>>()




    //构造
    init {
        loadMoreConfig?.let {

            //设置recyclerView 的滚动监听
            recyclerLayout.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrolled(rv: RecyclerView?, dx: Int, dy: Int) {
                    if (!recyclerLayout.canScrollVertically(-1)) {
                        it.onScrolledToTop()
                    } else if (!recyclerLayout.canScrollVertically(1)) {
                        it.onScrolledToBottom()
                        onScrolledToBottom()
                    } else if (dy < 0) {
                        it.onScrolledUp()
                    } else if (dy > 0) {
                        it.onScrolledDown()
                    }
                }

            })
        }

    }

    private fun onScrolledToBottom() {
        recyclerLayout.postDelayed({
            NoHttp.getRequestQueueInstance().add(LoadMoreConfig.WHAT_LOAD_MORE, loadMoreConfig!!.getRequest(), object : OnResponseListener<String> {
                override fun onStart(what: Int) {
                }

                override fun onSucceed(what: Int, response: Response<String>?) {
                    val count = itemCount
                    notifyItemRemoved(count)
                    response?.let { fragment?.doBusiness(what, it) }
                    recyclerLayout.recyclerView.scrollToPosition(count - 1)
                }

                override fun onFinish(what: Int) {


                }

                override fun onFailed(what: Int, response: Response<String>?) {
                    val rootView = getItem(itemCount - 1)?.rootView
                    rootView?.findViewById(R.id.tv_load_more)?.let {
                        val s = "load failed"
                        (it as TextView).text = s
                    }
                    rootView?.findViewById(R.id.iv_net_failed)?.let {
                        it.visibility = View.VISIBLE

                    }
                    rootView?.findViewById(R.id.pb_progress_bar)?.let {
                        it.visibility = View.INVISIBLE
                    }
                }
            })
        }, 1000)//fixme 这里默认延迟一秒 为了用户体验 如果觉得不需要 可以去掉postDelay
    }




    override fun getItemCount(): Int {
        if (loadMoreConfig != null) {
            return items.size + 1
        } else {
            return items.size
        }
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {


        /*if (loadMoreConfig != null) {
            //自定义 loadMoreConfig
            if (loadMoreConfig != null) {
                if (viewType == itemCount - 1) {
                    return loadMoreConfig!!.resId ?: R.layout.item_load_more
                } else {
                    return items[viewType].type
                }
            } else {
                //默认 loadMoreConfig
                if (viewType == itemCount - 1) {
                    return R.layout.item_load_more
                } else {
                    return items[viewType].type
                }
            }
        } else {
            return items[viewType].type
        }*/
        return ItemViewHolder.create(items[viewType])
    }


    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        if (loadMoreConfig != null) {
            //自定义 loadMOre
            if (loadMoreConfig != null) {
                if (position == itemCount - 1) {

                } else {
                    defaultBindTo(position, holder)
                }
            } else {
                //默认 loadMoreConfig
                if (position == itemCount - 1) {

                } else {
                    defaultBindTo(position, holder)
                }
            }
        } else {
            defaultBindTo(position, holder)
        }


    }

    private fun defaultBindTo(position: Int, holder: ItemViewHolder) {
        val item = items[position]
        item.position = position
        item.list = items
        item.size = itemCount
        item.recyclerView = recyclerLayout.recyclerView
        holder.bindTo(item, fragment, position)
    }


    ///////////////////////////////////////////////////////
    // operate items

    ///////////////////////////////////////////////////
    class ItemViewHolder(val rootView: View) : RecyclerView.ViewHolder(rootView) {

        fun bindTo(item: BaseItem<out ViewDataBinding>, fragment: BaseFragment<out ViewDataBinding>?, position: Int) {

//            binding.setVariable(BR.item, item)
            item.fragment = fragment
            item.rootView = rootView
            item.contentView.executePendingBindings()
            item.recyclerView?.post { item.initView() }
        }

        companion object {
            fun create(baseItem: BaseItem<out ViewDataBinding>): ItemViewHolder {
                return ItemViewHolder(baseItem.rootView)
            }
        }
    }

    /**
     * 核心方法 ：引入V7 DiffUtil (http://blog.csdn.net/zxt0601/article/details/52562770)
     * 取代 notifyDataSetChange
     * 自动计算新老数据集的差异，并根据差异情况调用以下方法
     * adapter.notifyItemRangeInserted(position, count);
     * adapter.notifyItemRangeRemoved(position, count);
     * adapter.notifyItemMoved(fromPosition, toPosition);
     * adapter.notifyItemRangeChanged(position, count, payload);
     */
    fun notifyDiff(diff: DiffCallBack) {

        //利用DiffUtil.calculateDiff()方法，传入一个规则DiffUtil.Callback对象，和是否检测移动item的 boolean变量，得到DiffUtil.DiffResult 的对象
        val diffResult = DiffUtil.calculateDiff(diff, true)

        //别忘了将新数据给Adapter
        setItems(diff.newItems)

        //利用DiffUtil.DiffResult对象的dispatchUpdatesTo（）方法，传入RecyclerView的Adapter，轻松成为文艺青年
        diffResult.dispatchUpdatesTo(this)

    }


    fun getItemsOf(start: Int, end: Int): List<BaseItem<out ViewDataBinding>> {
        return items.subList(start, end + 1)
    }




    fun setItems(items: List<BaseItem<out ViewDataBinding>>) {
        this.items.clear()
        if (items.isEmpty()) {
            //数据集合为空
            recyclerLayout.onItemsEmpty(true)
        } else {
            this.items.addAll(items)
            recyclerLayout.onItemsEmpty(false)
        }

    }






    /**
     * 获取集合中某一位置的 item
     * @param position item在集合中对应的位置，
     * 如果集合为空则返回 null
     */
    fun getItem(position: Int): BaseItem<out ViewDataBinding>? {
        return items.getOrNull(position)
    }

    /**
     * 获取集合对象
     * @return item 的集合对象
     */
    fun getItems(): List<BaseItem<out ViewDataBinding>> {
        return items
    }

    /**
     * @return 返回集合中最后一个满足用户自定义条件的 item，
     * 如果集合为空 则返回 null
     */
    fun lastItem(predicate: (BaseItem<out ViewDataBinding>) -> Boolean): BaseItem<out ViewDataBinding>? {
        return items.lastOrNull(predicate)
    }

    /**
     * @return 返回集合中第一个满足用户自定义条件的 item，
     * 如果集合为空 则返回 null
     */
    fun firstItem(predicate: (BaseItem<out ViewDataBinding>) -> Boolean): BaseItem<out ViewDataBinding>? {
        return items.firstOrNull(predicate)
    }

    /**
     * @return 返回集合中最后一个 item，
     * 如果集合为空 则返回 null
     */
    fun lastItem(): BaseItem<out ViewDataBinding>? {
        return items.lastOrNull()
    }

    /**
     * @return 返回集合中第一个 item，
     * 如果集合为空 则返回 null
     */
    fun firstItem(): BaseItem<out ViewDataBinding>? {
        return items.firstOrNull()
    }

    /**
     * 判断集合中是否含有具体的 item 对象
     * @param item 具体的 item 对象
     * @return true 包含该 item , false 不存在该 item
     */
    fun hasItem(item: BaseItem<out ViewDataBinding>): Boolean {
        return items.contains(item)
    }

    /**
     * 在 item 集合末尾新增一个 item
     * @param item item 对象
     */
    fun addItem(item: BaseItem<out ViewDataBinding>) {
        items.add(item)
        items.forEach {
            it.size = items.size
        }
    }

    /**
     * 插入一个 item 到指定位置
     * 如果 item 插入的位置不在最后 则后面的 item 内部的 position 将更新
     * @param item 插入的 item 对象
     * @param index 插入的 item 位置
     */
    fun addItem(item: BaseItem<out ViewDataBinding>, index: Int) {
        items.filter { it.position >= index }.forEach { it.position += 1 }
        items.add(index, item)
        items.forEach {
            it.size = items.size
        }
    }

    /**
     * 添加一个 item 集合
     * @param items 集合列表
     */
    fun addItems(items: List<BaseItem<out ViewDataBinding>>) {
        this.items.addAll(items)
        items.forEach {
            it.size = items.size
        }
    }

    /**
     * 移除具体的 item
     * @param item 需要移除具体的 item 对象
     */

    fun removeItem(item: BaseItem<out ViewDataBinding>) {
        items.remove(item)
        items.filter { it.position > item.position }.forEach {
            it.position -= 1
        }
        items.forEach {
            it.size = items.size
        }
    }

    /**
     * 移除单个 position 位置的 item
     * 该 position 位置后的 item 内部的 position 将更新
     * @param position 需要移除 item 的对应position
     */
    fun removeItemAt(position: Int) {
        items.remove(items[position])
        items.filter { it.position > position }.forEach {
            it.position -= 1
        }
        items.forEach {
            it.size = items.size
        }
    }

    /**
     * 移除对应区间内的 item
     * item 内部维护的 position 会自动更新
     * @param startPosition 起始位置position
     * @param endPosition 结束位置position
     */
    fun removeItems(startPosition: Int, endPosition: Int) {
        (startPosition..endPosition).forEach { items.removeAt(startPosition) }
        items.forEach {
            it.size = items.size
        }
    }


    /**
     * 清空 item 集合
     */
    fun clearItems() {
        items.clear()
    }


}